package me.bincker.formwork.web.core.config.mvc.advice

import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
import me.bincker.formwork.web.core.config.jackson.annotation.JsonHideView
import me.bincker.formwork.web.core.config.jackson.annotation.JsonHideViews
import me.bincker.formwork.web.core.config.jackson.filter.JsonHideViewPropertyFilter
import org.springframework.core.MethodParameter
import org.springframework.http.MediaType
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.http.converter.json.MappingJacksonValue
import org.springframework.http.server.ServerHttpRequest
import org.springframework.http.server.ServerHttpResponse
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice
import java.util.*

//==================================================自定义JsonFilter，实现与@JsonView相反的注解==================================================
@ControllerAdvice
class JsonHideViewResponseBodyAdvice : AbstractMappingJacksonResponseBodyAdvice() {
    override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean {
        return super.supports(returnType, converterType) &&
                (returnType.hasMethodAnnotation(JsonHideView::class.java) || returnType.hasMethodAnnotation(JsonHideViews::class.java))
    }

    override fun beforeBodyWriteInternal(mappingJacksonValue: MappingJacksonValue, mediaType: MediaType, methodParameter: MethodParameter, serverHttpRequest: ServerHttpRequest, serverHttpResponse: ServerHttpResponse) {
        val jsonHideViewAnnotation = methodParameter.getMethodAnnotation(JsonHideView::class.java)
        val jsonHideViewsAnnotation = methodParameter.getMethodAnnotation(JsonHideViews::class.java)
        val jsonHideViewList = LinkedList<JsonHideView>()
        if(jsonHideViewAnnotation != null) jsonHideViewList.add(jsonHideViewAnnotation)
        if(jsonHideViewsAnnotation != null) jsonHideViewList.addAll(jsonHideViewsAnnotation.value.toList())

        val filterProvider = SimpleFilterProvider()

        jsonHideViewList.forEach { jsonHideView ->
            filterProvider.addFilter(jsonHideView.name, JsonHideViewPropertyFilter(jsonHideView.value, jsonHideView.clazz))
        }
        mappingJacksonValue.filters = filterProvider
    }
}